﻿using System;
using CrossLayerCommunication;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTest
{
    [TestClass]
    public class TestMessage
    {
        [TestMethod]
        [ExpectedException(typeof(Exception))]
        public void TestMessageCreation()
        {
            //arrange - if first time messages would be called
            Message.AllMessages.Clear();
            
            Assert.AreEqual(0, Message.AllMessages.Count);

            MessageTester(message: new Message(-1, "Key", MessageType.Debug, 1, "Test", new DateTime(2011, 1, 1)),
                expectedId: -1, expectedKey: "Key", expectedType: MessageType.Debug, expectedArgs: new object[] { 1, "Test", new DateTime(2011, 1, 1) });
            Assert.AreEqual(0, Message.AllMessages.Count);

            MessageTester(message: Message.Create(-1, type: MessageType.Debug),
                expectedId: -1, expectedKey: null, expectedType: MessageType.Debug);
            Assert.AreEqual(1, Message.AllMessages.Count);

            MessageTester(message: Message.Create(-2, "Key", MessageType.Debug, 1, "Test", new DateTime(2011, 1, 1)),
                expectedId: -2, expectedKey: "Key", expectedType: MessageType.Debug, expectedArgs: new object[] { 1, "Test", new DateTime(2011, 1, 1) });
            Assert.AreEqual(2, Message.AllMessages.Count);

            MessageTester(message: Message.Create(-1, "Key", MessageType.Debug),
               expectedId: -1, expectedKey: "Key", expectedType: MessageType.Debug);
        }

        [TestMethod]
        public void TestMessageClone()
        {
            Message.AllMessages.Clear();

            IMessage message =  MessageHelper.CreateOrGetMessage(-1, type: MessageType.Info);
            IMessage clonedMessage = (IMessage)message.Clone();
            clonedMessage.Key = "Key";

            MessageTester(message: clonedMessage,
                expectedId: -1, expectedKey: "Key", expectedType: MessageType.Info);
        }

        [TestMethod]
        public void TestMessageEquals()
        {
            IMessage message1 = MessageHelper.CreateOrGetMessage(-4, type: MessageType.Info),
                    message2 = MessageHelper.CreateOrGetMessage(-4, type: MessageType.Error),
                    message3 = MessageHelper.CreateOrGetMessage(-3, type: MessageType.Info),
                    message4 = null;

            Assert.IsFalse(message1.Equals(message4));
            Assert.IsTrue(message1.Equals(message2));
            Assert.IsFalse(message1.Equals(message3));
        }

        [TestMethod]
        public void TestMessageChangeProperties()
        {
            IMessage message = MessageHelper.CreateOrGetMessage(-1);
            MessageTester(message: message,
                expectedId: -1, expectedKey: null, expectedType: MessageType.Error);

            message.Key = "Test";
            MessageTester(message: message,
                expectedId: -1, expectedKey: "Test", expectedType: MessageType.Error);

            message.Params = new object[3] { 1, "Test", new DateTime(2011, 1, 1) };
            MessageTester(message: new Message(-1, "Key", MessageType.Debug, 1, "Test", new DateTime(2011, 1, 1)),
                expectedId: -1, expectedKey: "Key", expectedType: MessageType.Debug, expectedArgs: new object[] { 1, "Test", new DateTime(2011, 1, 1) });
        }

        [TestMethod]
        public void TestTryGetMessageById()
        {
            //arrange - if first time messages would be called
            Message.AllMessages = new System.Collections.Concurrent.ConcurrentDictionary<int, IMessage>();

            Assert.AreEqual(0, Message.AllMessages.Count);
            MessageHelper.CreateOrGetMessage(-1);

            IMessage message;

            //act, assert
            Assert.IsFalse(Message.TryGetMessageById(1, out message));
            Assert.IsNull(message);

            Assert.IsTrue(Message.TryGetMessageById(-1, out message));
            Assert.IsNotNull(message);
            MessageTester(message: message,
                expectedId: -1, expectedKey: null, expectedType: MessageType.Error);
        }

        private void MessageTester(IMessage message, int expectedId, string expectedKey, MessageType expectedType, params object[] expectedArgs)
        {
            Assert.AreEqual(expectedId, message.Id);
            Assert.AreEqual(expectedKey, message.Key);
            Assert.AreEqual(expectedType, message.Type);

            Assert.AreEqual(expectedArgs.Length, message.Params.Length);
            for(int i=0;i<expectedArgs.Length;i++)
            {                    
                Assert.AreEqual(expectedArgs[i], message.Params[i]);
            }
        }
    }
}
